package com.Unidbg_hengdin.filehandle;

import com.alibaba.fastjson.util.IOUtils;
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Emulator;
import com.github.unidbg.Module;
import com.github.unidbg.arm.backend.Unicorn2Factory;
import com.github.unidbg.file.FileResult;
import com.github.unidbg.file.IOResolver;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.SystemPropertyHook;
import com.github.unidbg.linux.android.SystemPropertyProvider;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.linux.file.ByteArrayFileIO;
import com.github.unidbg.linux.file.SimpleFileIO;
import com.github.unidbg.memory.Memory;
import com.Unidbg_hengdin.System_cm.StudySystemPropertyHook;

import java.io.File;



public class xiaojianbangFile extends AbstractJni implements IOResolver {
    private final AndroidEmulator emulator;
    private final VM vm;
    private final Module module;

    private final DvmClass NativeHelperUtils;

    private final boolean logging;

    xiaojianbangFile(boolean logging) {
        this.logging = logging;

        emulator = AndroidEmulatorBuilder.for64Bit()
                .setProcessName("com.xiaojianbang.app")
                .addBackendFactory(new Unicorn2Factory(true))
                .setRootDir(new File("unidbg-android\\src\\test\\java\\com\\Unidbg_hengdin\\filehandle\\rootfs"))
                .build(); // 创建模拟器实例，要模拟32位或者64位，在这里区分
        final Memory memory = emulator.getMemory(); // 模拟器的内存操作接口
        memory.setLibraryResolver(new AndroidResolver(23)); // 设置系统类库解析
        // IOResolver 的注册
        emulator.getSyscallHandler().addIOResolver(this);
        //
        System.out.println(emulator.getFileSystem().getRootDir()); // 设置前：C:\Users\ADMINI~1\AppData\Local\Temp\rootfs\default 设置后：unidbg-android\src\test\java\com\xiaojianbang\filehandle\rootfs


        SystemPropertyHook systemPropertyHook = new SystemPropertyHook(emulator);
        systemPropertyHook.setPropertyProvider(new SystemPropertyProvider() {
            @Override
            public String getProperty(String key) {
                System.out.println("xiaojianbang __system_property_get: " + key);
                switch (key) {}
                return "";
            };
        });
        memory.addHookListener(systemPropertyHook);

        StudySystemPropertyHook hooker = new StudySystemPropertyHook(emulator);
        memory.addHookListener(hooker);

        vm = emulator.createDalvikVM(); // 创建Android虚拟机
        vm.setVerbose(logging); // 设置是否打印Jni调用细节      unidbg-android/src/test/java/com/Unidbg_hengdin/ndk/libxiaojianbang.so
        vm.setJni(this);
        DalvikModule dmA = vm.loadLibrary(new File("unidbg-android/src/test/java/com/Unidbg_hengdin/ndk/libxiaojianbangA.so"), false); // 加载libttEncrypt.so到unicorn虚拟内存，加载成功以后会默认调用init_array等函数
        DalvikModule dm = vm.loadLibrary(new File("unidbg-android/src/test/java/com/Unidbg_hengdin/filehandle/libxiaojianbang.so"), false); // 加载libttEncrypt.so到unicorn虚拟内存，加载成功以后会默认调用init_array等函数
//        dm.callJNI_OnLoad(emulator); // 手动执行JNI_OnLoad函数
        module = dm.getModule(); // 加载好的libttEncrypt.so对应为一个模块

        NativeHelperUtils = vm.resolveClass("com/xiaojianbang/ndk/NativeHelper");
    }

    void destroy() {
        IOUtils.close(emulator);
        if (logging) {
            System.out.println("destroy");
        }
    }

    public static void main(String[] args) throws Exception {
        com.Unidbg_hengdin.filehandle.xiaojianbangFile test = new com.Unidbg_hengdin.filehandle.xiaojianbangFile(true);

//        int data = test.callFun();
        test.callFun();

//        Inspector.inspect(data, "callFun");
//
        test.destroy();
    }

    void callFun() {

//        byte[] data = new byte[16];

//        调用 add 方法
//        int retval = NativeHelperUtils.callStaticJniMethodInt(emulator, "add(III)I", 0x100, 0x200, 0x300); // 执行Jni方法
//        System.out.println("res : 0x" + Integer.toHexString(retval));

//        调用MD5方法
//        StringObject md5_retval = NativeHelperUtils.callStaticJniMethodObject(emulator, "md5(Ljava/lang/String;)Ljava/lang/String;", new StringObject(vm,"123456")); // 执行Jni方法
//        System.out.println("md5_retval res : " + md5_retval.getValue());

//        调用encode 方法
        StringObject encodeRetval = NativeHelperUtils.callStaticJniMethodObject(emulator, "readSomething()"); // 执行Jni方法
        System.out.println("fileRead res : " + encodeRetval.getValue());


    }

    @Override
    public FileResult resolve(Emulator emulator, String pathname, int oflags) {
        System.out.println("pathname --------------------------------：" + pathname);
        if ("/proc/self/maps".equals(pathname)){
            // 返回一个文件路径，适用于文件内容较多的情况
            return FileResult.success(new SimpleFileIO(oflags, new File("F:\\unidbg-master\\unidbg-android\\src\\test\\java\\com\\Unidbg_hengdin\\filehandle\\maps"), pathname));
            //return FileResult.success(new ByteArrayFileIO(oflags, pathname, "hengdin test filehandler".getBytes()));
        }

        return null;
    }
}